package com.likeyoudo.views.utils;

import static android.content.Context.MODE_PRIVATE;

import android.util.Log;


import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

import cn.hutool.core.util.StrUtil;

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.blankj.utilcode.util.CacheMemoryStaticUtils;
import com.blankj.utilcode.util.SPUtils;
import com.blankj.utilcode.util.ToastUtils;
import com.likeyoudo.common.constant.HttpMethod;
import com.likeyoudo.common.constant.HttpStatus;
import com.likeyoudo.common.constant.LoginInfoSP;
import com.likeyoudo.common.msg.MsgEvent;
import com.likeyoudo.common.msg.MsgEventBuilder;

import okhttp3.*;
import okio.BufferedSink;

import org.greenrobot.eventbus.EventBus;
import org.jetbrains.annotations.NotNull;

import java.io.IOException;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * 请求方法封装
 *
 * @author LikeYouDo
 */

public class HttpRequest {
    public static final MediaType JSON_TYPE = MediaType.parse("application/json; charset=utf-8");
    public static final String HOST = "http://frp.likeyoudo.top:18082/prod-api";
    private static final OkHttpClient CLIENT = new OkHttpClient.Builder()
            .connectTimeout(10, TimeUnit.SECONDS)
            .readTimeout(30, TimeUnit.SECONDS)
            .writeTimeout(30, TimeUnit.SECONDS)
            .callTimeout(10, TimeUnit.SECONDS)
            .build();

    private static int maxRetryCount = 3;

    // 存放用户信息
    private static final SPUtils loginInfo = SPUtils.getInstance("loginInfo", MODE_PRIVATE);

    public static void request(String msgType, String requestMethod, String url, Headers.Builder headers, Map<String, String> queryParams, RequestBody requestBody, OkHttpClient client) {
        Request.Builder builder = new Request.Builder();
        HttpUrl.Builder httpUrlBuild = HttpUrl.parse(HOST + url).newBuilder();
        // 判断请求类型默认get
        switch (requestMethod) {
            case HttpMethod.POST:
                builder.post(requestBody);
                break;
            case HttpMethod.PUT:
                builder.put(requestBody);
                break;
            case HttpMethod.DELETE:
                if (requestBody == null) {
                    builder.delete();
                } else {
                    builder.delete(requestBody);
                }
                break;
            default:
                builder.get();
                if (queryParams != null && !queryParams.isEmpty()) {
                    for (String key : queryParams.keySet()) {
                        if (StrUtil.isNotBlank(queryParams.get(key))) {
                            httpUrlBuild.addQueryParameter(key, queryParams.get(key));
                        }
                    }
                }
        }

        // 获取缓存token信息
        String token = CacheMemoryStaticUtils.get(LoginInfoSP.TOKEN);
        token = token == null ? loginInfo.getString("token") : token;

        // 设置header值
        if (headers == null) {
            headers = new Headers.Builder();
            if (StrUtil.isNotBlank(token)) {
                headers.add("Authorization", "Bearer " + token);
            }
        } else {
            // 判断几个关键的请求头信息
            // 是否添加token信息
            if (!Boolean.parseBoolean(headers.get("isToken"))) {
                if (StrUtil.isNotBlank(token)) {
                    headers.add("Authorization", "Bearer " + token);
                }
            }
        }
        // 默认为json格式数据
        if (StrUtil.isBlank(headers.get("Content-Type"))) {
            headers.add("Content-Type", "application/json;charset=utf-8");
        }
        builder.headers(headers.build());
        // 设置url
        Request request = builder.url(httpUrlBuild.build()).build();

        // 是否自定义请求客户端
        if (client != null) {
            sendRequest(client, request, msgType, 0);
        } else {
            sendRequest(CLIENT, request, msgType, 0);
        }

    }

    private static void sendRequest(OkHttpClient client, Request request, String msgType, int retryCount) {
        Callback callback = new Callback() {
            @Override
            public void onFailure(@NotNull Call call, @NotNull IOException e) {
                // 请求失败,toast提示
                if (retryCount < maxRetryCount) {
                    ToastUtils.showLong("请求失败,10秒后重试,第"+retryCount+"次重试");
                    sendRequest(client, request, msgType, retryCount + 1);
                }else{
                    ToastUtils.showLong("已"+retryCount+"次尝试,请检查网络或其他可能的问题");
                }

            }

            @Override
            public void onResponse(@NotNull Call call, @NotNull Response response) throws IOException {
                if (response.body() != null) {
                    String body = response.body().string();
                    JSONObject obj = JSON.parseObject(body);

                    // 请求成功
                    if (obj.getInteger("code") == HttpStatus.UNAUTHORIZED) {
                        ToastUtils.showShort("登录已过期,请重新登录,3秒后跳转到登录页");
                        // 清除token
                        CacheMemoryStaticUtils.remove(LoginInfoSP.TOKEN);
                        LoginInfoSP.getSPUtils().remove(LoginInfoSP.TOKEN, true);
                        // 清空页面堆栈并跳转到登录页
                        try {
                            Thread.sleep(3000);
                        } catch (InterruptedException e) {
                            throw new RuntimeException(e);
                        }
                        LoginUtils.logout();
                    } else if (response.isSuccessful()) {
                        MsgEventBuilder builder = MsgEvent.builder().type(msgType);
                        // 直接整个存放
                        builder.data(body);
                        EventBus.getDefault().post(builder.build());
                    } else {
                        // 处理请求失败的情况
                        Log.e("ruoyi-requests", body);
                        ToastUtils.showShort(obj.getString("msg"));
                    }
                }
            }
        };

        client.newCall(request).enqueue(callback);
    }

    /**
     * get请求
     *
     * @param url 请求地址
     */
    public static void get(String msgType, String url) {
        get(msgType, url, null, null);
    }

    /**
     * get请求
     *
     * @param url 请求地址
     */
    public static void get(String msgType, String url, Map<String, String> queryParams) {
        get(msgType, url, null, queryParams);
    }

    /**
     * get请求
     *
     * @param url     请求地址
     * @param headers 请求头
     */
    public static void get(String msgType, String url, Headers.Builder headers, Map<String, String> queryParams) {
        request(msgType, HttpMethod.GET, url, headers, queryParams, null, null);
    }

    /**
     * post请求
     *
     * @param url 请求地址
     */
    public static void post(String msgType, String url) {
        post(msgType, url, null, new RequestBody() {
            @Nullable
            @Override
            public MediaType contentType() {
                return JSON_TYPE;
            }

            @Override
            public void writeTo(@NonNull BufferedSink bufferedSink) throws IOException {

            }
        });
    }

    /**
     * post请求
     *
     * @param url         请求地址
     * @param requestBody 请求体
     */
    public static void post(String msgType, String url, RequestBody requestBody) {
        post(msgType, url, null, requestBody);
    }

    /**
     * post请求
     *
     * @param url         请求地址
     * @param headers     请求头
     * @param requestBody 请求体
     */
    public static void post(String msgType, String url, Headers.Builder headers, RequestBody requestBody) {
        request(msgType, HttpMethod.POST, url, headers, null, requestBody, null);
    }

    /**
     * put请求
     *
     * @param url         请求地址
     * @param requestBody 请求体
     */
    public static void put(String msgType, String url, RequestBody requestBody) {
        put(msgType, url, null, requestBody);
    }

    /**
     * put请求
     *
     * @param url         请求地址
     * @param headers     请求头
     * @param requestBody 请求体
     */
    public static void put(String msgType, String url, Headers.Builder headers, RequestBody requestBody) {
        request(msgType, HttpMethod.PUT, url, headers, null, requestBody, null);
    }

    /**
     * delete请求
     *
     * @param url 请求地址
     */
    public static void delete(String msgType, String url) {
        delete(msgType, url, null, null);
    }

    /**
     * delete请求
     *
     * @param url         请求地址
     * @param requestBody 请求体
     */
    public static void delete(String msgType, String url, RequestBody requestBody) {
        delete(msgType, url, null, requestBody);
    }

    /**
     * delete请求
     *
     * @param url         请求地址
     * @param headers     请求头
     * @param requestBody 请求体
     */
    public static void delete(String msgType, String url, Headers.Builder headers, RequestBody requestBody) {
        request(msgType, HttpMethod.DELETE, url, headers, null, requestBody, null);
    }

}
